/*
 * SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: Unlicense OR CC0-1.0
 */

/****************************************************************************
*
* This is the demo to test the BLE throughput. It should be used together with throughput_client demo.
*
****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "freertos/semphr.h"

#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_defs.h"
#include "esp_bt_main.h"
#include "esp_bt_device.h"
#include "esp_gatt_common_api.h"
#include "esp_timer.h"

#include "sdkconfig.h"
#include "pic_packet.h"
#include "key_input.h"
#include "battery.h"

#define GATTS_TAG "GATTS_DEMO"

extern QueueHandle_t gpio_evt_queue;

#define LED_RED     34
#define LED_GREEN   36
#define LED_BLUE    35

//camera include
#include <nvs_flash.h>
#include "esp_camera.h"

#define CAM_PIN_PWDN -1  //power down is not used
#define CAM_PIN_RESET -1 //software reset will be performed
#define CAM_PIN_XCLK 17
#define CAM_PIN_SIOD 26 
#define CAM_PIN_SIOC 21 

#define CAM_PIN_D7 18
#define CAM_PIN_D6 16
#define CAM_PIN_D5 15
#define CAM_PIN_D4 12
#define CAM_PIN_D3 10
#define CAM_PIN_D2 8
#define CAM_PIN_D1 9
#define CAM_PIN_D0 11
#define CAM_PIN_VSYNC 20
#define CAM_PIN_HREF 19
#define CAM_PIN_PCLK 13

static camera_config_t camera_config = {
    .pin_pwdn = CAM_PIN_PWDN,
    .pin_reset = CAM_PIN_RESET,
    .pin_xclk = CAM_PIN_XCLK,
    .pin_sccb_sda = CAM_PIN_SIOD,
    .pin_sccb_scl = CAM_PIN_SIOC,

    .pin_d7 = CAM_PIN_D7,
    .pin_d6 = CAM_PIN_D6,
    .pin_d5 = CAM_PIN_D5,
    .pin_d4 = CAM_PIN_D4,
    .pin_d3 = CAM_PIN_D3,
    .pin_d2 = CAM_PIN_D2,
    .pin_d1 = CAM_PIN_D1,
    .pin_d0 = CAM_PIN_D0,
    .pin_vsync = CAM_PIN_VSYNC,
    .pin_href = CAM_PIN_HREF,
    .pin_pclk = CAM_PIN_PCLK,

    //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
    .xclk_freq_hz = 20000000,
    .ledc_timer = LEDC_TIMER_0,
    .ledc_channel = LEDC_CHANNEL_0,

    .pixel_format = PIXFORMAT_JPEG,
    .frame_size = FRAMESIZE_240X240,

    .jpeg_quality = 50, //0-63, for OV series camera sensors, lower number means higher quality
    .fb_count = 1,       //When jpeg mode is used, if fb_count more than one, the driver will work in continuous mode.
    .fb_location = CAMERA_FB_IN_DRAM,
    .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
};

static esp_err_t init_camera(void)
{
    //initialize the camera
    esp_err_t err = esp_camera_init(&camera_config);
    if (err != ESP_OK)
    {
        ESP_LOGE(GATTS_TAG, "Camera Init Failed");
        return err;
    }

    return ESP_OK;
}

/**********************************************************
 * picture packet
 **********************************************************/
#define NOTIFY_LEN    495
Pic_Packet pic_packet;
static uint8_t packetdata[NOTIFY_LEN] = {0};

/**********************************************************
 * Thread/Task reference
 **********************************************************/
#ifdef CONFIG_BLUEDROID_PINNED_TO_CORE
#define BLUETOOTH_TASK_PINNED_TO_CORE              (CONFIG_BLUEDROID_PINNED_TO_CORE < CONFIG_FREERTOS_NUMBER_OF_CORES ? CONFIG_BLUEDROID_PINNED_TO_CORE : tskNO_AFFINITY)
#else
#define BLUETOOTH_TASK_PINNED_TO_CORE              (0)
#endif

#define SECOND_TO_USECOND          1000000


#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
#define GATTS_NOTIFY_LEN    495
static SemaphoreHandle_t gatts_semaphore;
static bool can_send_notify = false;
static uint8_t indicate_data[GATTS_NOTIFY_LEN] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a};

//jpg picture data
static uint8_t jpeg_pic[] = 
{0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x32,0x22,0x26,0x2c,0x26,0x1f,0x32,0x2c,0x29,0x2c,0x38,0x35,0x32,0x3b,0x4b,0x7d,0x51,0x4b,0x45,0x45,0x4b,0x99,0x6d,0x74,0x5b,0x7d,0xb5,0x9f,0xbf,0xbc,0xb2,0x9f,0xaf,0xac,0xc8,0xe1,0xff,0xf4,0xc8,0xd5,0xff,0xd8,0xac,0xaf,0xfa,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xc2,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0x00,0x43,0x01,0x35,0x38,0x38,0x4b,0x42,0x4b,0x93,0x51,0x51,0x93,0xff,0xce,0xaf,0xce,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc4,0x00,0x1f,0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xc4,0x00,0xb5,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7d,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xff,0xc4,0x00,0x1f,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xc4,0x00,0xb5,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xff,0xc0,0x00,0x11,0x08,0x00,0xf0,0x00,0xf0,0x03,0x01,0x21,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xff,0xda,0x00,0x0c,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0x45,0xe1,0xaa,0x6a,0x92,0x02,0x96,0x98,0x0a,0x29,0x69,0x08,0x4a,0x28,0x18,0x94,0x50,0x01,0x49,0x4c,0x41,0x49,0x40,0xc2,0x92,0x80,0x12,0x92,0x80,0x12,0x8a,0x00,0x4a,0x29,0x80,0x53,0xe1,0x1f,0x39,0xfa,0x50,0x22,0x59,0x3a,0x53,0x25,0xa4,0x04,0x74,0x62,0x98,0x06,0x29,0x68,0x02,0x3a,0x96,0x33,0x95,0xa4,0x31,0xf4,0xb4,0x80,0x5a,0x5a,0x04,0x25,0x14,0x0c,0x29,0x28,0x00,0xa4,0xa0,0x02,0x92,0x98,0x05,0x25,0x00,0x14,0x94,0x00,0x94,0x94,0x00,0x51,0x4c,0x41,0x52,0xdb,0xf4,0x63,0x48,0x07,0x3f,0xde,0x14,0x84,0x67,0x77,0xd2,0x80,0x21,0xa7,0x53,0x00,0xa2,0x80,0x23,0xa5,0x43,0x86,0xa4,0x51,0x35,0x2d,0x21,0x05,0x3a,0x80,0x0a,0x4a,0x00,0x29,0x28,0x00,0xa4,0xa0,0x02,0x92,0x80,0x0a,0x4a,0x60,0x25,0x25,0x00,0x14,0x94,0x00,0x51,0x40,0x05,0x4f,0x07,0xdc,0xa0,0x42,0xff,0x00,0xcb,0x4f,0xc2,0x84,0xe7,0x3e,0xe6,0x80,0x20,0x14,0xb4,0xc0,0x5a,0x28,0x02,0x3a,0x4a,0x91,0x92,0xa1,0xc8,0xa7,0xd0,0x01,0x4a,0x28,0x01,0x69,0x28,0x00,0xa4,0xa0,0x02,0x92,0x80,0x0a,0x4a,0x00,0x29,0x29,0x80,0x94,0x50,0x02,0x52,0x50,0x01,0x45,0x00,0x15,0x66,0x2f,0xf5,0x62,0x81,0x0d,0xfe,0xf9,0xa7,0x27,0x0a,0x28,0x11,0x0b,0x70,0xe6,0x8a,0x63,0x0a,0x5a,0x00,0x8e,0x9b,0x52,0x31,0xc8,0x7e,0x6a,0x96,0x80,0x16,0x96,0x80,0x16,0x92,0x80,0x0a,0x4a,0x00,0x29,0x28,0x00,0xa4,0xa6,0x01,0x49,0x40,0x09,0x49,0x40,0x09,0x45,0x00,0x14,0x50,0x01,0x57,0x31,0xb5,0x71,0xe9,0x40,0x88,0x4f,0x29,0xf5,0xa9,0x68,0x02,0x29,0x7f,0xd6,0x53,0x69,0x80,0x52,0xd0,0x04,0x54,0x52,0x18,0xda,0x92,0x36,0x2c,0x39,0xfa,0x50,0x04,0x94,0xb4,0x80,0x5a,0x28,0x01,0x29,0x28,0x00,0xa4,0xa0,0x04,0xa2,0x80,0x12,0x8a,0x00,0x4a,0x4a,0x60,0x25,0x14,0x00,0x51,0x40,0x0a,0x9f,0x7c,0x7d,0x6a,0xd3,0xf4,0x34,0x08,0x8b,0xfb,0xa2,0xa6,0x5a,0x42,0x23,0xb9,0xfb,0xeb,0xf4,0xa8,0xea,0x86,0x2d,0x2d,0x00,0x41,0x4c,0x2f,0x9e,0x94,0x86,0x20,0xab,0xb6,0xc9,0xb4,0x73,0xd1,0x39,0xfc,0x68,0x01,0xbd,0x79,0xf5,0xa2,0x90,0x0b,0x4b,0x40,0x0d,0xa2,0x80,0x12,0x8a,0x00,0x4a,0x28,0x01,0x28,0xa0,0x04,0xa4,0xa6,0x02,0x51,0x40,0x05,0x14,0xc4,0x3e,0x1f,0xf5,0x82,0xa6,0x93,0xee,0xd2,0x01,0xa3,0xef,0x55,0x88,0xc5,0x21,0x11,0x5d,0xfd,0xe4,0xa8,0xaa,0x86,0x2d,0x39,0x7a,0xd0,0x05,0x45,0xcd,0x38,0xae,0x7d,0xa8,0x01,0x22,0x5f,0x9f,0x9e,0xdc,0xd5,0x8b,0x83,0xb6,0x35,0x8b,0xb9,0xe5,0xa8,0x28,0x6a,0x9c,0x8a,0x75,0x48,0x85,0xa5,0xa0,0x06,0xd2,0x50,0x01,0x49,0x40,0x05,0x14,0x00,0x94,0x94,0x00,0x52,0x53,0x01,0x28,0xa0,0x02,0x90,0x9a,0x04,0x49,0x6f,0xf7,0xaa,0x47,0xa0,0x04,0x4e,0xb5,0x71,0x06,0x05,0x00,0x55,0x9f,0x99,0xcf,0xb7,0x14,0xca,0x63,0x16,0x9e,0x28,0x11,0x4c,0x53,0xe8,0x01,0xc8,0x70,0xe3,0x3d,0x3b,0xd1,0x2b,0x6f,0x94,0xb5,0x22,0x86,0xa9,0xc1,0xa9,0x69,0x08,0x5a,0x5a,0x00,0x43,0x49,0x40,0x05,0x25,0x00,0x14,0x94,0x00,0x52,0x50,0x01,0x49,0x4c,0x04,0xa2,0x80,0x06,0xa6,0xd3,0x11,0x2d,0xbf,0xfa,0xcf,0xc2,0xa5,0x7a,0x40,0x11,0x7f,0xad,0x15,0x72,0x82,0x91,0x9f,0x9d,0xcc,0x5b,0xd4,0xd3,0xa9,0x92,0x2d,0x3e,0x90,0xca,0x62,0x9d,0x4c,0x03,0xb5,0x14,0x80,0x4a,0x91,0x0e,0x56,0x90,0x0e,0xa5,0xa0,0x00,0xd2,0x50,0x01,0x45,0x00,0x25,0x14,0x00,0x94,0x50,0x02,0x52,0x50,0x01,0x45,0x30,0x1a,0xd4,0x94,0xc4,0x49,0x07,0xfa,0xe5,0xab,0x12,0x54,0x80,0x89,0xfe,0xb0,0x54,0xd7,0x07,0x10,0xb7,0xbf,0x14,0xd0,0xca,0x9d,0xe9,0xd4,0xc4,0x28,0xa7,0x52,0x19,0x56,0x93,0x75,0x30,0x01,0xcd,0x3f,0xbf,0xd6,0x80,0x12,0x84,0xe0,0xd4,0x8c,0x96,0x8a,0x04,0x2d,0x14,0x00,0x94,0x52,0x00,0xa4,0xa6,0x01,0x49,0x40,0x05,0x25,0x00,0x14,0x94,0x00,0x8d,0x4d,0xaa,0x10,0xf8,0xcf,0xce,0xbf,0x5a,0xb7,0x2f,0x4a,0x90,0x18,0x3e,0xf8,0xa5,0xbb,0x6e,0x55,0x3f,0x1a,0x68,0x64,0x34,0xea,0x04,0x3a,0x96,0x81,0x94,0x8d,0x36,0x98,0x87,0x21,0xa9,0x16,0x81,0x87,0xb5,0x18,0xa4,0x03,0xd7,0xa5,0x3a,0x90,0xc2,0x96,0x81,0x05,0x14,0x80,0x4a,0x29,0x80,0x52,0x50,0x02,0x51,0x40,0x09,0x49,0x40,0x08,0xf4,0x95,0x42,0x01,0x57,0xe5,0xe5,0x0d,0x48,0x11,0x0f,0xe1,0xa6,0x4a,0x77,0x4c,0x7f,0x2a,0x60,0x27,0x57,0xc7,0xb5,0x38,0xfd,0xef,0xc3,0x34,0xc0,0x29,0x69,0x0c,0xa3,0x49,0x4c,0x43,0x96,0xa6,0x5a,0x06,0x21,0x38,0x6a,0x7d,0x20,0x14,0x52,0xd4,0x80,0xb4,0x85,0x80,0xef,0x4c,0x06,0xac,0x99,0x3d,0x29,0xf4,0x00,0x94,0x50,0x02,0x51,0x40,0x09,0x49,0x40,0x09,0x45,0x30,0x1a,0xdd,0x69,0x29,0x88,0x5a,0xbf,0xd6,0x21,0xf4,0xa9,0x02,0x20,0x71,0x10,0x3e,0x95,0x12,0x50,0x03,0xa3,0xff,0x00,0x5a,0xb4,0xff,0x00,0xe2,0x5f,0xa5,0x30,0x1d,0x45,0x21,0x99,0x94,0xea,0xa0,0x1e,0xb5,0x28,0xa0,0x06,0x3f,0x5a,0x7a,0x1a,0x00,0x7d,0x33,0xcc,0xf4,0xe6,0xa4,0x06,0x97,0x63,0x4d,0xaa,0x10,0xe4,0x19,0x6c,0x55,0x99,0x47,0x29,0xf4,0xa4,0x32,0x3a,0x29,0x00,0x94,0x50,0x02,0x52,0x50,0x02,0x51,0x40,0x08,0xd4,0xda,0x62,0x14,0x75,0xab,0xb1,0x7f,0xa8,0x5a,0x00,0x8d,0xbf,0xd4,0x7f,0xc0,0xb1,0x4c,0xfe,0x1a,0x00,0x5e,0x9b,0x0f,0xbd,0x4c,0xe3,0xe7,0x1f,0x5a,0x00,0x5a,0x4a,0x91,0x99,0xb4,0x55,0x88,0x78,0xa7,0xad,0x03,0x12,0x5e,0xb4,0xa9,0xd2,0x80,0x10,0xf5,0xa2,0x80,0x12,0x96,0x90,0x89,0xad,0x53,0x2c,0x4d,0x3e,0x43,0xb9,0xcd,0x03,0x1b,0x49,0x48,0x02,0x92,0x80,0x12,0x8a,0x00,0x4a,0x4a,0x00,0x6b,0xd2,0x53,0x10,0x55,0xc8,0x3f,0xd5,0x7e,0x34,0x98,0x10,0xbf,0xdf,0xc5,0x1d,0x4d,0x00,0x2c,0x9c,0xab,0x63,0xb0,0xcd,0x4d,0x21,0xe3,0x3f,0x43,0x4c,0x64,0x84,0x52,0x54,0x01,0x97,0x4b,0x5a,0x08,0x5a,0x91,0x68,0x18,0xaf,0xf7,0x69,0x13,0xae,0x28,0x00,0x6f,0xbd,0x49,0x40,0x82,0x8a,0x40,0x5c,0x88,0x79,0x50,0xd4,0x55,0x23,0x0a,0x4a,0x00,0x29,0x29,0x80,0x94,0x94,0x00,0x52,0x50,0x02,0x35,0x32,0x98,0x82,0xac,0xc5,0xf7,0x4d,0x00,0x30,0x8f,0x9a,0x9c,0x83,0x9a,0x06,0x4d,0xe5,0x91,0x13,0x71,0xd6,0x99,0xd6,0xd9,0x7f,0xdd,0xc5,0x00,0x59,0x5f,0x99,0x41,0xa3,0x15,0x00,0x64,0x51,0x5a,0x08,0x70,0xa9,0x16,0x80,0x1d,0x4d,0xef,0x40,0xc1,0xba,0xd2,0x52,0x00,0xa5,0x8c,0x6e,0x7a,0x42,0x2e,0x4d,0xc6,0x17,0xf1,0xa8,0x68,0x18,0x52,0x52,0x00,0xa4,0xa6,0x02,0x52,0x50,0x01,0x4d,0xa0,0x04,0x6e,0x94,0xca,0x62,0x16,0xa7,0x87,0xd2,0x81,0x8f,0x61,0xf3,0x2f,0xd6,0xa5,0x81,0x76,0xbb,0x67,0xad,0x03,0x45,0x8a,0xa9,0x1f,0xfa,0xa2,0xbe,0x8f,0x4c,0x19,0x35,0xbf,0xfa,0x91,0x52,0xd4,0x58,0x2c,0x62,0x52,0xd5,0x88,0x72,0xd4,0x82,0x90,0x0b,0x40,0xa6,0x01,0x27,0x6a,0x6d,0x21,0x05,0x4f,0x6a,0xbd,0xe9,0x30,0x1e,0xe7,0x73,0x93,0x4c,0xa4,0x30,0xa4,0xa0,0x02,0x92,0x98,0x09,0x49,0x40,0x09,0x49,0x40,0x01,0xe9,0x51,0xd3,0x00,0xab,0x16,0xdf,0xeb,0x97,0xe9,0x40,0x16,0x25,0x4d,0xbb,0x4f,0xfb,0x42,0x9e,0x7f,0xe3,0xe5,0x3d,0x0a,0x9a,0x0a,0x24,0x35,0x5c,0x7f,0xac,0x9c,0x7d,0x1a,0x81,0x0f,0x83,0xa3,0x0f,0x7a,0x9a,0x98,0xd1,0x8b,0x45,0x04,0x8e,0x15,0x25,0x02,0x0a,0x70,0xa0,0x62,0x49,0xda,0x9b,0x48,0x42,0x55,0xd0,0x3c,0xb8,0xfe,0x82,0x80,0x22,0xa2,0xa4,0x62,0x51,0x40,0x09,0x49,0x4c,0x02,0x92,0x80,0x1b,0x45,0x00,0x07,0xa5,0x47,0x4c,0x41,0x53,0x41,0xfe,0xb1,0x3e,0xb4,0x0c,0xb7,0x78,0x7f,0x70,0x7d,0x7a,0xd2,0xcb,0xf7,0xe3,0x3e,0xf4,0xc6,0x48,0xfd,0x2a,0xbe,0x3f,0xd2,0xb1,0xfd,0xe4,0xa0,0x43,0xe0,0x3f,0x3b,0x7e,0x06,0xa7,0xa0,0xa4,0x62,0xd2,0xd0,0x48,0x2d,0x48,0x28,0x01,0x45,0x3e,0x80,0x18,0xfd,0x69,0x28,0x10,0xe8,0x97,0x7b,0x63,0xda,0xac,0xce,0xdf,0xaf,0x34,0x01,0x16,0xec,0xd1,0x52,0x31,0x28,0xa0,0x02,0x92,0x80,0x12,0x92,0x80,0x12,0x92,0x98,0x05,0x47,0x40,0x82,0xa5,0x43,0x8c,0x1f,0x4a,0x43,0x2e,0x5c,0x7c,0xca,0x47,0xb5,0x38,0x10,0xd6,0xe8,0xff,0x00,0x43,0x4c,0x09,0x1f,0xa5,0x55,0x6e,0x26,0x81,0xbe,0xa2,0x98,0x0f,0x8f,0x8b,0x8f,0xce,0xac,0xd0,0x52,0x31,0x69,0x68,0x20,0x51,0x52,0x52,0x00,0xa7,0x8a,0x63,0x18,0xdf,0x78,0xd3,0x7b,0xd2,0x11,0x62,0xd8,0x7f,0x17,0xb5,0x24,0xe7,0xe6,0x34,0x86,0x40,0x38,0x39,0xc5,0x3b,0x79,0xf4,0xa6,0x01,0xb8,0xd1,0xb9,0xbd,0x29,0x00,0x99,0x6a,0x32,0x68,0x01,0x32,0x69,0x33,0x4c,0x42,0x64,0xd1,0x48,0x02,0x92,0x98,0x05,0x3c,0x7d,0xd3,0x40,0x17,0xba,0xa0,0x34,0x90,0xff,0x00,0xc7,0xa1,0x1e,0x99,0x14,0x8a,0x26,0x3c,0xc7,0xf8,0x55,0x7b,0x8e,0x23,0x56,0xfe,0xeb,0x83,0x4c,0x42,0xb7,0xfa,0xf0,0x7d,0xea,0xd5,0x05,0x23,0x16,0x96,0x99,0x03,0x85,0x3a,0x81,0x8b,0x4e,0x14,0x08,0x6b,0xfd,0xe3,0x49,0xd5,0xa8,0x02,0xdc,0x7f,0x24,0x1f,0x41,0x55,0x9c,0xf6,0xef,0x52,0x31,0xab,0xd6,0x9d,0x8a,0x00,0x31,0x49,0xed,0x40,0x05,0x14,0x00,0x53,0x4d,0x00,0x27,0x02,0x92,0x81,0x06,0x45,0x36,0x98,0x05,0x3d,0x28,0x19,0x72,0x2f,0xf5,0x0b,0x4b,0x01,0xe2,0x41,0xef,0x40,0x0f,0x84,0xfe,0xe4,0x54,0x73,0xfc,0xd6,0xd2,0x0f,0x6a,0x60,0x24,0x8f,0x95,0x47,0xf5,0x5d,0xd5,0x72,0x91,0x48,0xc6,0xc5,0x14,0xc8,0x1c,0x29,0xc2,0x80,0x16,0x9d,0xda,0x80,0x1b,0x20,0x60,0x14,0xb7,0x7a,0x23,0x19,0x6f,0xc2,0x80,0x2d,0x5c,0x9c,0x28,0x5f,0x53,0x9a,0xaa,0xdf,0xeb,0x6a,0x46,0x1d,0x0f,0x14,0x64,0xfa,0x50,0x01,0x93,0x41,0xcd,0x00,0x02,0x93,0x9a,0x00,0x4a,0x4a,0x04,0x20,0xe9,0x4b,0x40,0x09,0x4d,0xa6,0x01,0x4e,0x4a,0x06,0x5c,0xb7,0xff,0x00,0x53,0xf4,0x34,0x91,0xff,0x00,0xac,0x90,0x7d,0x29,0x01,0x24,0x07,0xe4,0x23,0xde,0x86,0x19,0xdc,0xbe,0xa2,0xa8,0x08,0x53,0xe6,0xb4,0x53,0xf5,0x15,0x72,0x13,0xba,0x25,0x3e,0xd4,0x8a,0x32,0x68,0xa6,0x40,0xea,0x75,0x00,0x2d,0x0d,0xf7,0x29,0x0c,0x6e,0x72,0x7b,0x54,0xb6,0xc3,0x3f,0x8d,0x02,0x16,0xe1,0xbf,0xd2,0x4f,0xa0,0xe2,0xa3,0x1c,0xcd,0x40,0xc4,0x43,0x9c,0x9a,0x75,0x21,0x89,0xde,0x82,0x68,0x10,0x52,0x50,0x01,0x48,0x68,0x01,0xa3,0xa5,0x2d,0x30,0x12,0x98,0x7a,0xd0,0x02,0x53,0xd6,0x80,0x2d,0xda,0xfd,0xc7,0xfa,0xd2,0x7f,0xcb,0xcf,0xd5,0x4d,0x20,0x1f,0x0f,0xde,0x90,0x54,0x9f,0xc5,0x4c,0x08,0x22,0xcf,0x97,0x22,0xff,0x00,0x76,0x4a,0xb3,0x6b,0xfe,0xa7,0x1e,0x94,0x0d,0x19,0x74,0x53,0x24,0x70,0xa7,0x50,0x03,0xa8,0x7f,0xb9,0x40,0x11,0xd5,0xbb,0x7c,0x02,0x4f,0x65,0xa4,0x32,0xb9,0x24,0xb1,0x27,0xbd,0x22,0xfd,0xd9,0x28,0x01,0x14,0xe0,0x52,0xee,0xa0,0x03,0xbd,0x1d,0xa8,0x00,0x1d,0x28,0xa4,0x01,0x9a,0x43,0xd2,0x80,0x1a,0x29,0x73,0x40,0x09,0x9a,0x69,0xa6,0x03,0x69,0xe2,0x80,0x2c,0xdb,0x1f,0x9d,0x87,0xa8,0xa7,0x4b,0xc3,0xa9,0xf7,0xa4,0x02,0x42,0xc7,0xce,0xfa,0xad,0x4a,0x4f,0xf2,0xa6,0x04,0x79,0xc4,0xf3,0xaf,0xaa,0xee,0xa9,0xed,0x7f,0x8f,0xeb,0x40,0xcc,0xda,0x28,0x24,0x70,0xa7,0x53,0x01,0xd4,0x49,0xf7,0x68,0x01,0xab,0xf7,0xb3,0x56,0xbf,0xd5,0xda,0xfd,0x70,0x28,0x19,0x5b,0xf8,0x8d,0x37,0x3f,0x25,0x20,0x11,0x7a,0x53,0xa8,0x10,0x0a,0x4e,0x3b,0x8a,0x43,0x17,0xf8,0x69,0xbd,0xe8,0x10,0x0f,0xbe,0x29,0x58,0xf0,0xd4,0x14,0x32,0x8c,0xd0,0x21,0x3f,0x0a,0x43,0xf4,0xa0,0x04,0xa7,0x0a,0x60,0x58,0xb7,0xff,0x00,0x5c,0x2a,0x4b,0x8f,0xbb,0x9f,0x43,0x48,0x04,0xfb,0xb3,0x2d,0x4b,0x9c,0x30,0xa6,0x03,0x0e,0x3e,0xda,0xbc,0x7d,0xe5,0xc5,0x2d,0x99,0xfd,0xe6,0x3d,0x45,0x20,0x28,0xd1,0x54,0x21,0xe2,0x96,0x80,0x1f,0x4d,0x7e,0xa2,0x80,0x16,0x25,0xed,0x56,0x2e,0x78,0x64,0x4f,0x41,0x40,0xca,0xb4,0xa7,0x3f,0x85,0x20,0x00,0x7e,0xb4,0xaa,0x68,0x00,0x34,0x94,0x00,0xb9,0xe2,0x9b,0x40,0x84,0xc9,0x1c,0x8a,0x59,0x33,0xdd,0xc1,0xfa,0x1a,0x43,0x1b,0x45,0x00,0x25,0x23,0x50,0x03,0x29,0xc2,0xa8,0x09,0xe1,0xff,0x00,0x5a,0x9f,0x5a,0x9a,0xe7,0xfd,0x51,0xa9,0x01,0x0f,0x54,0x3f,0x4a,0x95,0xb8,0x34,0x0c,0x8a,0x7e,0x26,0x85,0xbd,0x0e,0x29,0xd1,0x7c,0xb7,0x5f,0x89,0x14,0x08,0xa5,0x45,0x50,0x0e,0x14,0xea,0x04,0x3c,0x53,0x1b,0xef,0xd0,0x04,0xd6,0xe3,0x91,0x4b,0x73,0xfe,0xbd,0xe8,0x19,0x5f,0xa0,0xa4,0x3d,0x69,0x00,0xea,0x4a,0x00,0x33,0x4b,0x9c,0x50,0x01,0x49,0x40,0x85,0x5d,0xb9,0xf9,0xba,0x7a,0xd4,0x65,0xbd,0x28,0x18,0xd0,0x71,0x4e,0xa0,0x02,0x90,0xf4,0xa0,0x06,0xd3,0x85,0x00,0x48,0x0e,0x18,0x1f,0x7a,0xb7,0x2f,0x20,0xd2,0x02,0x1c,0xe6,0xdd,0x4f,0xb5,0x58,0x93,0xa5,0x30,0x21,0xbb,0xff,0x00,0x8f,0x7c,0xfa,0x11,0x4b,0x9f,0xf4,0x8c,0xfb,0x83,0x48,0x0a,0x74,0xb5,0x42,0x1d,0x4e,0x14,0x08,0x78,0xa6,0x1f,0xf5,0x94,0x0c,0xb9,0x66,0x2a,0x3b,0xd1,0xfb,0xdf,0xaa,0xd2,0x28,0xae,0x69,0x9d,0xa8,0x10,0x9d,0xe9,0x73,0x40,0x09,0x9a,0x5a,0x60,0x19,0xf6,0xa2,0x90,0x83,0x35,0x1d,0x03,0x0a,0x5a,0x06,0x14,0x1a,0x04,0x25,0x28,0xa0,0x07,0xff,0x00,0x0d,0x5e,0x3f,0x74,0x1f,0x6a,0x40,0x42,0xbf,0xea,0x7f,0x13,0x53,0xaf,0x31,0xaf,0xd2,0x80,0x23,0x93,0x9b,0x67,0xf6,0xa8,0x73,0xf7,0x7f,0xdd,0xa0,0x08,0x29,0x7b,0xd5,0x08,0x75,0x38,0x50,0x03,0xc5,0x31,0x79,0x92,0x80,0x34,0xad,0xc7,0xc9,0x50,0xde,0x7d,0xe4,0x3f,0x5a,0x0a,0x2b,0x54,0x72,0xd2,0x01,0xb8,0xa5,0xc5,0x02,0x0c,0x52,0xe2,0x80,0x12,0x8c,0x50,0x03,0x48,0xa3,0x1c,0x50,0x03,0x45,0x38,0xd0,0x03,0x68,0x34,0xc0,0x4a,0x29,0x01,0x25,0x5c,0x8f,0x98,0x57,0xe9,0x48,0x06,0xc5,0xff,0x00,0x2d,0x07,0xa1,0xa7,0xc5,0xfe,0xa4,0x53,0x01,0x71,0x94,0x71,0xea,0x2a,0xa2,0xfd,0xd5,0x34,0x80,0xff,0xd9,}
;
static uint8_t jpeg_pic2[] = 
{0xff,0xd8,0xff,0xe0,0x00,0x10,0x4a,0x46,0x49,0x46,0x00,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xdb,0x00,0x43,0x00,0x32,0x22,0x26,0x2c,0x26,0x1f,0x32,0x2c,0x29,0x2c,0x38,0x35,0x32,0x3b,0x4b,0x7d,0x51,0x4b,0x45,0x45,0x4b,0x99,0x6d,0x74,0x5b,0x7d,0xb5,0x9f,0xbf,0xbc,0xb2,0x9f,0xaf,0xac,0xc8,0xe1,0xff,0xf4,0xc8,0xd5,0xff,0xd8,0xac,0xaf,0xfa,0xff,0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xc2,0xf1,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xdb,0x00,0x43,0x01,0x35,0x38,0x38,0x4b,0x42,0x4b,0x93,0x51,0x51,0x93,0xff,0xce,0xaf,0xce,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xc4,0x00,0x1f,0x00,0x00,0x01,0x05,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xc4,0x00,0xb5,0x10,0x00,0x02,0x01,0x03,0x03,0x02,0x04,0x03,0x05,0x05,0x04,0x04,0x00,0x00,0x01,0x7d,0x01,0x02,0x03,0x00,0x04,0x11,0x05,0x12,0x21,0x31,0x41,0x06,0x13,0x51,0x61,0x07,0x22,0x71,0x14,0x32,0x81,0x91,0xa1,0x08,0x23,0x42,0xb1,0xc1,0x15,0x52,0xd1,0xf0,0x24,0x33,0x62,0x72,0x82,0x09,0x0a,0x16,0x17,0x18,0x19,0x1a,0x25,0x26,0x27,0x28,0x29,0x2a,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xff,0xc4,0x00,0x1f,0x01,0x00,0x03,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0xff,0xc4,0x00,0xb5,0x11,0x00,0x02,0x01,0x02,0x04,0x04,0x03,0x04,0x07,0x05,0x04,0x04,0x00,0x01,0x02,0x77,0x00,0x01,0x02,0x03,0x11,0x04,0x05,0x21,0x31,0x06,0x12,0x41,0x51,0x07,0x61,0x71,0x13,0x22,0x32,0x81,0x08,0x14,0x42,0x91,0xa1,0xb1,0xc1,0x09,0x23,0x33,0x52,0xf0,0x15,0x62,0x72,0xd1,0x0a,0x16,0x24,0x34,0xe1,0x25,0xf1,0x17,0x18,0x19,0x1a,0x26,0x27,0x28,0x29,0x2a,0x35,0x36,0x37,0x38,0x39,0x3a,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xff,0xc0,0x00,0x11,0x08,0x00,0xf0,0x00,0xf0,0x03,0x01,0x21,0x00,0x02,0x11,0x01,0x03,0x11,0x01,0xff,0xda,0x00,0x0c,0x03,0x01,0x00,0x02,0x11,0x03,0x11,0x00,0x3f,0x00,0x65,0x15,0x24,0x0b,0x4b,0x48,0x0a,0xa4,0xee,0x24,0xd0,0xab,0x93,0x54,0x32,0x4f,0xba,0x28,0x12,0x29,0xeb,0xc5,0x02,0x25,0x18,0xf5,0xa1,0x85,0x21,0x91,0xe2,0x93,0x65,0x30,0x10,0xa5,0x37,0x6d,0x00,0x34,0xd1,0x40,0xc7,0xa9,0xed,0x56,0x51,0xb3,0xc7,0x7a,0x42,0x1d,0x4b,0x40,0x84,0xa5,0xa0,0x02,0x9b,0x40,0x09,0x45,0x00,0x25,0x36,0x81,0x09,0x4d,0xa0,0x63,0xe9,0x69,0x00,0x51,0x40,0xc8,0x64,0x5c,0x1f,0xad,0x28,0xf9,0x45,0x30,0x10,0x82,0xdd,0x7a,0xd3,0xb6,0x0f,0x4a,0x60,0x29,0x89,0x7b,0x0c,0x52,0x6c,0x91,0x7e,0xe3,0xfe,0x74,0x80,0x0b,0x38,0xfb,0xeb,0xf9,0x51,0xbc,0x7d,0x28,0x01,0xd4,0x62,0x80,0x1a,0xc8,0x0f,0x6a,0x61,0x18,0xa0,0x06,0x54,0xc0,0xf4,0xa0,0x64,0xea,0xdb,0x85,0x3a,0x91,0x22,0x51,0x4c,0x05,0xa4,0xa0,0x06,0xd1,0x40,0x09,0x4d,0xa0,0x04,0xa4,0xa0,0x43,0xe8,0xa0,0x61,0x4b,0x48,0x63,0x1b,0xb5,0x33,0xaf,0xf4,0xa6,0x21,0xde,0xb8,0xed,0x4f,0x39,0x07,0xa5,0x30,0x17,0x34,0xb4,0x86,0x2e,0x29,0x1e,0x3c,0xf6,0xa4,0x04,0x46,0x3c,0x1e,0x29,0x73,0xcf,0x22,0x81,0x0e,0x14,0x92,0x0e,0x29,0x8c,0x81,0x87,0x14,0xe8,0xfa,0x53,0x01,0xe0,0xe0,0xe4,0x54,0xc0,0xe4,0x66,0x90,0x85,0xa2,0x80,0x0a,0x28,0x01,0x0d,0x25,0x00,0x25,0x36,0x80,0x1b,0x49,0x40,0x0f,0xa5,0xa4,0x30,0xa5,0xa0,0x44,0x64,0xe4,0xe3,0xdf,0x14,0x63,0xd0,0xd5,0x00,0x9f,0x74,0x7d,0x69,0xf8,0xa0,0x07,0x81,0x4e,0x02,0x90,0x12,0x01,0x41,0x14,0x86,0x34,0xad,0x33,0xc9,0xc8,0xa0,0x06,0x00,0xc1,0xb6,0xf5,0xf4,0xa7,0xe0,0x0e,0xa7,0x1e,0xf4,0x01,0x04,0xaa,0x41,0xc5,0x32,0x3f,0xbd,0x8a,0x60,0x49,0x4a,0xad,0xb4,0xfb,0x52,0x11,0x35,0x14,0xc6,0x14,0x50,0x20,0xa6,0xd0,0x03,0x69,0xb4,0x00,0x94,0xda,0x06,0x49,0x4b,0x48,0x41,0x48,0xcd,0x8e,0x9d,0x69,0x8c,0x89,0x41,0xf3,0x09,0xfd,0x69,0xfd,0xfd,0xa8,0x01,0x40,0xee,0x69,0xcb,0x4c,0x44,0x82,0x9c,0x29,0x00,0xf1,0x4f,0xa4,0x31,0x76,0xd2,0xb0,0xf9,0x68,0x02,0xb9,0xe0,0x13,0x4c,0xeb,0x40,0xc8,0xe6,0xfe,0x0f,0xa5,0x43,0x1f,0xfa,0xda,0x60,0x4c,0x69,0x9f,0xad,0x21,0x0f,0x8d,0xb1,0xc1,0x3c,0x54,0xb4,0xc4,0x25,0x14,0x00,0x52,0x1a,0x00,0x69,0xa6,0xd0,0x03,0x69,0x28,0x02,0x5a,0x29,0x00,0x54,0x6b,0xf3,0x31,0x6a,0x06,0x4b,0x8a,0x31,0xed,0x4c,0x04,0xa7,0x0a,0x60,0x3c,0x53,0x85,0x21,0x0f,0x14,0xfa,0x91,0x8e,0xa7,0x37,0xdd,0xa0,0x0a,0x73,0x11,0xf7,0x69,0x91,0x0e,0x6a,0x86,0x12,0x8e,0x54,0x7a,0x0a,0xae,0x06,0x27,0xc5,0x02,0x26,0xa6,0x9a,0x42,0x1b,0x52,0x46,0xdd,0xa8,0x18,0xfa,0x4a,0x60,0x14,0x50,0x21,0xa6,0x99,0x40,0x09,0x49,0x40,0x12,0xd1,0x48,0x63,0x64,0x19,0x5f,0xc6,0x9a,0x3e,0x5f,0xa5,0x31,0x0f,0x62,0xc5,0x7e,0x42,0x05,0x38,0x31,0xd9,0x86,0xeb,0x40,0x06,0x29,0xc0,0x50,0x03,0xe9,0xe2,0x80,0x1c,0x29,0xe2,0xa4,0x63,0x85,0x39,0xbe,0xe1,0xa0,0x0a,0x48,0x9c,0x63,0xad,0x4d,0x14,0x43,0x39,0x34,0xc6,0x57,0x9f,0xfd,0x61,0xaa,0xe3,0x9b,0x8f,0xc2,0x98,0x89,0x69,0x28,0x01,0xb4,0xda,0x04,0x4a,0x8d,0x9f,0xad,0x38,0x9d,0xa3,0x27,0xa5,0x03,0x11,0x0e,0xf1,0x95,0xe6,0x8a,0x00,0x0d,0x32,0x81,0x09,0x49,0x48,0x09,0x28,0xa0,0x02,0x9b,0x83,0xd3,0xf3,0xa0,0x04,0xc6,0xd2,0x69,0xff,0x00,0x2d,0x30,0x1c,0x29,0xf4,0x00,0xea,0x70,0xa0,0x09,0x05,0x3c,0x52,0x01,0xc2,0x87,0x5c,0x8a,0x91,0x8d,0xf2,0xa8,0x3f,0x2d,0x03,0x28,0xcb,0xdc,0xd4,0x30,0x8f,0xbc,0xc6,0xac,0x44,0xb4,0x94,0x80,0x4a,0x69,0xa0,0x06,0x67,0x1c,0xd3,0x59,0x8b,0x9e,0x69,0xa0,0x2d,0x59,0xf1,0x1e,0xec,0x76,0x26,0x9b,0xd2,0x80,0x0a,0x69,0xa0,0x41,0x49,0x48,0x07,0xd1,0x40,0xc2,0x96,0x80,0x23,0x6f,0xbf,0x4e,0x08,0x69,0x80,0xf5,0x40,0x29,0xc2,0x81,0x0e,0xa7,0x8a,0x06,0x3c,0x54,0x82,0xa4,0x43,0xc5,0x3e,0x90,0xc2,0xa1,0xb8,0x38,0x4a,0x00,0xce,0x98,0xfc,0x86,0x92,0x21,0xfb,0xb1,0x56,0x03,0xa8,0xa4,0x02,0x54,0x6e,0xf8,0xe9,0xc9,0xa0,0x08,0xb3,0x9e,0xa6,0x8a,0xa0,0x2e,0xa8,0xf2,0xed,0x7a,0x7b,0x53,0x28,0x01,0x29,0x29,0x08,0x29,0x28,0x18,0xfa,0x29,0x08,0x29,0x68,0x18,0xc6,0xfb,0xd4,0xe1,0x40,0x0f,0x14,0xea,0x62,0x16,0x9c,0x29,0x0c,0x7d,0x38,0x1a,0x40,0x3b,0x35,0x28,0x34,0x80,0x75,0x57,0xbb,0xfb,0xb4,0x0c,0xce,0x9b,0x92,0x10,0x77,0xa9,0x2a,0x84,0x14,0xd6,0x21,0x7a,0x9a,0x00,0x85,0xa4,0x27,0xda,0x99,0x54,0x01,0x4b,0x4c,0x0b,0x97,0x07,0x6c,0x71,0xfd,0x6a,0x3a,0x80,0x12,0x8a,0x62,0x0a,0x4a,0x40,0x3f,0x14,0x50,0x01,0x4b,0x48,0x63,0x5b,0x91,0x40,0xaa,0x02,0x41,0x4f,0x14,0x08,0x75,0x14,0x86,0x19,0xa5,0xcd,0x21,0x8e,0x15,0x2a,0xd2,0x11,0x35,0x57,0xbb,0xfb,0xa2,0x80,0x33,0xc7,0x33,0x93,0xe9,0x52,0x55,0x01,0x0b,0x4b,0xfd,0xda,0x87,0xaf,0x24,0xe6,0x98,0x0b,0x8c,0xd4,0x9e,0x58,0xf7,0xfc,0xe9,0x80,0x6c,0xf7,0x14,0xdd,0x84,0x53,0x02,0xdc,0xe3,0x31,0x46,0xd5,0x15,0x40,0x85,0xa4,0xa0,0x02,0x9b,0x40,0x12,0xd1,0x40,0xc4,0xa2,0x80,0x12,0x93,0xa5,0x00,0x28,0x34,0xf0,0xd4,0xc0,0x76,0x68,0xcd,0x48,0x0b,0x4e,0xa0,0x07,0x54,0x8b,0x40,0x89,0xc7,0x4a,0x8a,0xe4,0x7e,0xef,0xe9,0x48,0xa3,0x2d,0x5b,0x8f,0xad,0x46,0x49,0xaa,0x10,0x94,0x9d,0x2a,0x80,0x33,0x4f,0xfa,0x9a,0x60,0x2e,0x69,0xe3,0x83,0x40,0x07,0x4e,0x45,0x39,0x48,0x61,0x91,0x52,0x01,0x45,0x21,0x05,0x25,0x03,0x24,0xa2,0x90,0x82,0x8c,0x53,0x18,0x94,0xd2,0x28,0x02,0x3c,0xd3,0xc3,0x50,0x03,0xf7,0x53,0x96,0x90,0x0f,0x14,0xea,0x62,0x0a,0x91,0x68,0x02,0xc2,0x1a,0x18,0x6e,0x52,0x2a,0x0a,0x31,0x4a,0x30,0x3b,0x48,0xe4,0x53,0x71,0x5a,0x08,0x69,0x3d,0xa9,0x29,0x80,0xab,0xd7,0x34,0x85,0xb2,0x69,0x8c,0x91,0x6a,0x4a,0x42,0x02,0x69,0x31,0xdc,0x0f,0xad,0x31,0x0b,0xbf,0x07,0x93,0xd6,0x9d,0x48,0x02,0x92,0x90,0x12,0x51,0x48,0x61,0x45,0x02,0x0a,0x29,0x0c,0x42,0x3d,0xa9,0xbb,0x05,0x00,0x34,0xae,0x2a,0x58,0xfa,0x53,0x02,0x4a,0x5a,0x62,0x0a,0x70,0x34,0x80,0x91,0x5f,0x14,0x49,0x74,0x10,0x7a,0xd2,0x19,0x94,0x49,0x72,0x59,0xfb,0xf3,0x4d,0x2d,0x5a,0x0c,0x6d,0x14,0x80,0x53,0xe9,0x49,0x40,0x12,0xad,0x49,0xda,0x82,0x48,0x4b,0x53,0xd4,0x93,0xd3,0xad,0x31,0x8f,0xdb,0xb9,0x7b,0x54,0x4a,0xdb,0x68,0x11,0x29,0x60,0x2a,0x16,0x3b,0xa9,0x0c,0xb3,0xba,0x9d,0x52,0x01,0x45,0x00,0x14,0x52,0x00,0xa4,0xa0,0x02,0x90,0x71,0x4c,0x44,0x82,0x96,0xa8,0x02,0x8c,0xd2,0x10,0x16,0xaa,0xae,0xf9,0xa6,0x32,0x22,0x73,0x49,0x41,0x42,0x51,0x4c,0x04,0xa7,0x50,0x03,0xd7,0xad,0x39,0xb6,0xd2,0x11,0x11,0xa7,0x47,0x40,0x13,0xf6,0xa8,0x65,0xeb,0x9a,0x62,0x12,0x33,0xdb,0x14,0x30,0xc1,0xf6,0xa0,0x65,0xbc,0x51,0x8a,0x80,0x0a,0x28,0x00,0xa2,0x90,0x05,0x25,0x30,0x0a,0x4e,0xf4,0x00,0xe0,0x69,0xd5,0x42,0x12,0x92,0x81,0x15,0xde,0x5d,0xe7,0x03,0xee,0xff,0x00,0x3a,0x8e,0x82,0x86,0xd1,0x4c,0x61,0x45,0x20,0x0a,0x5a,0x62,0x24,0x14,0x84,0xf1,0x40,0x88,0xe9,0xeb,0xd6,0x81,0x93,0x66,0x90,0x80,0xdd,0x68,0x11,0x03,0x0d,0xad,0x4f,0x53,0xbb,0x83,0x40,0xcb,0x54,0x54,0x00,0x51,0x40,0x05,0x14,0x80,0x29,0x29,0x80,0x53,0x5a,0x80,0x14,0x53,0xaa,0x84,0x2d,0x56,0x92,0x4d,0xfc,0x29,0xf9,0x7f,0x9d,0x00,0x45,0x49,0x41,0x41,0x45,0x30,0x12,0x8a,0x00,0x5a,0x75,0x20,0x0a,0x43,0x4c,0x42,0xad,0x2d,0x20,0x1f,0xde,0x9c,0x29,0x88,0x6b,0xd4,0x74,0x86,0x5c,0xa2,0xa4,0x41,0x45,0x00,0x14,0x52,0x18,0x94,0x99,0xa0,0x02,0x8a,0x04,0x20,0xa7,0x55,0x01,0x04,0xb2,0x6f,0xf9,0x57,0xa7,0xf3,0xa8,0xa9,0x94,0x14,0x94,0x00,0x52,0x53,0x00,0xa2,0x80,0x1d,0x45,0x21,0x09,0x45,0x31,0x8e,0x14,0xb4,0x84,0x14,0xf5,0xa6,0x02,0x37,0x4a,0x8f,0xbd,0x00,0x5d,0xa2,0xa0,0x02,0x8a,0x04,0x14,0x50,0x30,0xa4,0x34,0x80,0x4e,0x83,0x26,0xa1,0x79,0xb2,0x30,0x94,0xc0,0x97,0xa0,0xa8,0x65,0x93,0x3f,0x28,0xe9,0xfc,0xe9,0x81,0x1d,0x14,0xc6,0x25,0x14,0x00,0x94,0x53,0x00,0xed,0x40,0xa0,0x05,0xa2,0x81,0x05,0x2d,0x20,0x16,0x9d,0x4c,0x04,0xa7,0x0a,0x00,0x6b,0x1a,0x41,0xd6,0x90,0x17,0x28,0xa9,0x00,0xa2,0x90,0x05,0x14,0xc0,0x63,0xc8,0x13,0xeb,0xe9,0x51,0x19,0xcf,0x61,0x4d,0x01,0x1f,0xcd,0x2b,0x75,0xa9,0xf1,0x1c,0x5d,0x69,0x81,0x03,0x48,0x5f,0xaf,0x4f,0x4a,0x6d,0x31,0x85,0x14,0x00,0x51,0x48,0x04,0xa2,0x80,0x0a,0x28,0x01,0x68,0xa6,0x01,0x4b,0x48,0x05,0xa5,0x14,0x08,0x28,0xcd,0x00,0x25,0x28,0xa6,0x05,0xba,0x2a,0x00,0x29,0x29,0x08,0x29,0x71,0x4c,0x0a,0x6c,0xdb,0xdb,0x34,0xda,0xb2,0x89,0x10,0xed,0x56,0x6e,0xf4,0xce,0x5b,0xe6,0x34,0x80,0x4a,0x28,0x00,0xa2,0x80,0x12,0x8a,0x60,0x14,0x50,0x01,0x45,0x20,0x16,0x8a,0x60,0x25,0x2d,0x20,0x16,0x96,0x98,0x82,0x8a,0x00,0x29,0x68,0x02,0xdd,0x15,0x02,0x10,0xd3,0x33,0x40,0xc5,0x43,0xf3,0x53,0x67,0x93,0xf8,0x01,0xfa,0xd3,0x02,0xb5,0x15,0x43,0x0a,0x4a,0x00,0x5a,0x28,0x01,0x28,0xa0,0x02,0x8a,0x00,0x28,0xa0,0x02,0x8a,0x00,0x29,0x68,0x01,0x29,0x69,0x00,0xb4,0x94,0xc0,0x5a,0x28,0x10,0x53,0xa8,0x02,0xdd,0x15,0x02,0x1a,0x6a,0x33,0x40,0x0c,0xdd,0xb7,0xa7,0x5a,0x8a,0xa8,0xa0,0xa2,0x80,0x0a,0x4a,0x60,0x14,0xb4,0x00,0x94,0x52,0x00,0xa2,0x80,0x12,0x96,0x98,0x05,0x14,0x80,0x5a,0x4a,0x00,0x28,0xa0,0x05,0xa2,0x80,0x0a,0x5a,0x62,0x0a,0x5a,0x40,0x5b,0xa2,0xa4,0x43,0x5a,0xab,0xbb,0xfa,0x53,0x43,0x19,0x49,0x4c,0xa0,0xa5,0xa0,0x42,0x51,0x4c,0x02,0x8a,0x00,0x28,0xa0,0x02,0x8a,0x00,0x29,0x28,0x00,0xa5,0xa0,0x02,0x92,0x80,0x16,0x8a,0x00,0x5a,0x4a,0x00,0x75,0x14,0x08,0x4a,0x28,0x19,0x76,0x92,0xa4,0x92,0xbc,0xaf,0x9e,0x01,0xf9,0x7f,0x9d,0x47,0x4c,0xa1,0x28,0xa6,0x01,0x45,0x00,0x14,0x50,0x01,0x45,0x00,0x14,0x50,0x01,0x49,0x40,0x05,0x14,0x00,0xb4,0x52,0x01,0x28,0xa6,0x01,0x45,0x03,0x16,0x8a,0x04,0x2d,0x19,0xa0,0x41,0x45,0x00,0x5c,0xa6,0xb9,0xc2,0x1a,0x91,0x15,0x69,0x29,0x94,0x14,0x53,0x00,0xa2,0x90,0x05,0x14,0x0c,0x29,0x29,0x80,0x52,0xd0,0x21,0x28,0xa0,0x02,0x8a,0x00,0x28,0xa0,0x61,0x45,0x21,0x05,0x2d,0x00,0x14,0x53,0x00,0xa2,0x81,0x0b,0x49,0x40,0xcb,0xb5,0x0c,0xed,0xc0,0x5f,0x5e,0x6a,0x49,0x20,0xa2,0xa8,0xa0,0xa2,0x81,0x85,0x14,0x84,0x14,0x50,0x02,0x52,0xd3,0x01,0x28,0xa0,0x02,0x8a,0x00,0x28,0xa4,0x01,0x45,0x00,0x14,0x50,0x01,0x4b,0x4c,0x61,0x45,0x21,0x05,0x14,0xc0,0x28,0xa0,0x0b,0x95,0x55,0x9b,0x2c,0x4d,0x4a,0x24,0x6d,0x15,0x45,0x85,0x25,0x02,0x16,0x8a,0x00,0x28,0xa0,0x02,0x8a,0x00,0x29,0x28,0x00,0xa2,0x81,0x85,0x14,0x00,0x51,0x48,0x41,0x45,0x30,0x0a,0x5a,0x40,0x25,0x2d,0x30,0x0a,0x29,0x00,0xb4,0x94,0xc0,0x9e,0x47,0xdb,0xc0,0xeb,0xfc,0xaa,0x0a,0x42,0x41,0xcd,0x14,0xca,0x0a,0x28,0x10,0x51,0x40,0x05,0x25,0x00,0x2d,0x25,0x03,0x0a,0x5a,0x04,0x25,0x14,0x00,0x51,0x40,0x05,0x14,0x00,0x51,0x40,0x0b,0x49,0x40,0x05,0x2d,0x20,0x0a,0x29,0x88,0x28,0xa0,0x03,0xde,0x8a,0x43,0x0a,0x4a,0x63,0x16,0x8a,0x04,0x14,0x52,0x00,0xa2,0x98,0x09,0x45,0x03,0x16,0x92,0x80,0x0a,0x28,0x10,0x51,0x40,0xc2,0x8a,0x00,0x4a,0x5a,0x04,0x19,0xa2,0x80,0x16,0x92,0x80,0x0a,0x28,0x00,0xa5,0xa0,0x0f,0xff,0xd9,}
;

#endif /* #if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT) */

#if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT)
static bool start = false;
static uint64_t write_len = 0;
static uint64_t start_time = 0;
static uint64_t current_time = 0;
#endif /* #if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT) */

static bool is_connect = false;
///Declare the static function
static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param);

#define GATTS_SERVICE_UUID_TEST_A   0x00FF
#define GATTS_CHAR_UUID_TEST_A      0xFF01
#define GATTS_DESCR_UUID_TEST_A     0x3333
#define GATTS_NUM_HANDLE_TEST_A     4

#define GATTS_SERVICE_UUID_TEST_B   0x00EE
#define GATTS_CHAR_UUID_TEST_B      0xEE01
#define GATTS_DESCR_UUID_TEST_B     0x2222
#define GATTS_NUM_HANDLE_TEST_B     4

#define TEST_DEVICE_NAME            "THROUGHPUT_DEMO"
#define TEST_MANUFACTURER_DATA_LEN  17

#define GATTS_DEMO_CHAR_VAL_LEN_MAX 0x40

#define PREPARE_BUF_MAX_SIZE 1024

static uint8_t char1_str[] = {0x11,0x22,0x33};
static esp_gatt_char_prop_t a_property = 0;

static esp_attr_value_t gatts_demo_char1_val =
{
    .attr_max_len = GATTS_DEMO_CHAR_VAL_LEN_MAX,
    .attr_len     = sizeof(char1_str),
    .attr_value   = char1_str,
};

static uint8_t adv_config_done = 0;
#define adv_config_flag      (1 << 0)
#define scan_rsp_config_flag (1 << 1)

#ifdef CONFIG_EXAMPLE_SET_RAW_ADV_DATA
static uint8_t raw_adv_data[] = {
        0x02, 0x01, 0x06,
        0x02, 0x0a, 0xeb, 0x03, 0x03, 0xab, 0xcd
};
static uint8_t raw_scan_rsp_data[] = {
        0x0f, 0x09, 0x45, 0x53, 0x50, 0x5f, 0x47, 0x41, 0x54, 0x54, 0x53, 0x5f, 0x44,
        0x45, 0x4d, 0x4f
};
#else

static uint8_t adv_service_uuid128[32] = {
    /* LSB <--------------------------------------------------------------------------------> MSB */
    //first uuid, 16bit, [12],[13] is the value
    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xEE, 0x00, 0x00, 0x00,
    //second uuid, 32bit, [12], [13], [14], [15] is the value
    0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
};

// The length of adv data must be less than 31 bytes
//static uint8_t test_manufacturer[TEST_MANUFACTURER_DATA_LEN] =  {0x12, 0x23, 0x45, 0x56};
//adv data
static esp_ble_adv_data_t adv_data = {
    .set_scan_rsp = false,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 0x0006, //slave connection min interval, Time = min_interval * 1.25 msec
    .max_interval = 0x000C, //slave connection max interval, Time = max_interval * 1.25 msec
    .appearance = 0x00,
    .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data =  NULL, //&test_manufacturer[0],
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = 32,
    .p_service_uuid = adv_service_uuid128,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};
// scan response data
static esp_ble_adv_data_t scan_rsp_data = {
    .set_scan_rsp = true,
    .include_name = true,
    .include_txpower = true,
    .min_interval = 0x0006,
    .max_interval = 0x000C,
    .appearance = 0x00,
    .manufacturer_len = 0, //TEST_MANUFACTURER_DATA_LEN,
    .p_manufacturer_data =  NULL, //&test_manufacturer[0],
    .service_data_len = 0,
    .p_service_data = NULL,
    .service_uuid_len = 32,
    .p_service_uuid = adv_service_uuid128,
    .flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT),
};

#endif /* CONFIG_EXAMPLE_SET_RAW_ADV_DATA */

static esp_ble_adv_params_t adv_params = {
    .adv_int_min        = 0x20,
    .adv_int_max        = 0x40,
    .adv_type           = ADV_TYPE_IND,
    .own_addr_type      = BLE_ADDR_TYPE_PUBLIC,
    //.peer_addr            =
    //.peer_addr_type       =
    .channel_map        = ADV_CHNL_ALL,
    .adv_filter_policy = ADV_FILTER_ALLOW_SCAN_ANY_CON_ANY,
};

#define PROFILE_NUM 1
#define PROFILE_A_APP_ID 0

struct gatts_profile_inst {
    esp_gatts_cb_t gatts_cb;
    uint16_t gatts_if;
    uint16_t app_id;
    uint16_t conn_id;
    uint16_t service_handle;
    esp_gatt_srvc_id_t service_id;
    uint16_t char_handle;
    esp_bt_uuid_t char_uuid;
    esp_gatt_perm_t perm;
    esp_gatt_char_prop_t property;
    uint16_t descr_handle;
    esp_bt_uuid_t descr_uuid;
};

/* One gatt-based profile one app_id and one gatts_if, this array will store the gatts_if returned by ESP_GATTS_REG_EVT */
static struct gatts_profile_inst gl_profile_tab[PROFILE_NUM] = {
    [PROFILE_A_APP_ID] = {
        .gatts_cb = gatts_profile_a_event_handler,
        .gatts_if = ESP_GATT_IF_NONE,       /* Not get the gatt_if, so initial is ESP_GATT_IF_NONE */
    },
};

typedef struct {
    uint8_t                 *prepare_buf;
    int                     prepare_len;
} prepare_type_env_t;

static prepare_type_env_t a_prepare_write_env;

void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param);
void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param);

static uint8_t check_sum(uint8_t *addr, uint16_t count)
{
    uint32_t sum = 0;

    if (addr == NULL || count == 0) {
        return 0;
    }

    for(int i = 0; i < count; i++) {
        sum = sum + addr[i];
    }

    while (sum >> 8) {
        sum = (sum & 0xff) + (sum >> 8);
    }

    return (uint8_t)~sum;
}


static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
    switch (event) {
#ifdef CONFIG_EXAMPLE_SET_RAW_ADV_DATA
    case ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT:
        adv_config_done &= (~adv_config_flag);
        if (adv_config_done==0){
            esp_ble_gap_start_advertising(&adv_params);
        }
        break;
    case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT:
        adv_config_done &= (~scan_rsp_config_flag);
        if (adv_config_done==0){
            esp_ble_gap_start_advertising(&adv_params);
        }
        break;
#else
    case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
        adv_config_done &= (~adv_config_flag);
        if (adv_config_done == 0){
            esp_ble_gap_start_advertising(&adv_params);
        }
        break;
    case ESP_GAP_BLE_SCAN_RSP_DATA_SET_COMPLETE_EVT:
        adv_config_done &= (~scan_rsp_config_flag);
        if (adv_config_done == 0){
            esp_ble_gap_start_advertising(&adv_params);
        }
        break;
#endif
    case ESP_GAP_BLE_ADV_START_COMPLETE_EVT:
        //advertising start complete event to indicate advertising start successfully or failed
        if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            ESP_LOGE(GATTS_TAG, "Advertising start failed");
        }
        break;
    case ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT:
        if (param->adv_stop_cmpl.status != ESP_BT_STATUS_SUCCESS) {
            ESP_LOGE(GATTS_TAG, "Advertising stop failed");
        }
        else {
            ESP_LOGI(GATTS_TAG, "Stop adv successfully");
        }
        break;
    case ESP_GAP_BLE_UPDATE_CONN_PARAMS_EVT:
         ESP_LOGI(GATTS_TAG, "update connection params status = %d, min_int = %d, max_int = %d,conn_int = %d,latency = %d, timeout = %d",
                  param->update_conn_params.status,
                  param->update_conn_params.min_int,
                  param->update_conn_params.max_int,
                  param->update_conn_params.conn_int,
                  param->update_conn_params.latency,
                  param->update_conn_params.timeout);
        break;
    default:
        break;
    }
}

void example_write_event_env(esp_gatt_if_t gatts_if, prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
    esp_gatt_status_t status = ESP_GATT_OK;
    if (param->write.need_rsp) {
        if (param->write.is_prep) {
            if (param->write.offset > PREPARE_BUF_MAX_SIZE) {
                status = ESP_GATT_INVALID_OFFSET;
            } else if ((param->write.offset + param->write.len) > PREPARE_BUF_MAX_SIZE) {
                status = ESP_GATT_INVALID_ATTR_LEN;
            }

            if (status == ESP_GATT_OK && prepare_write_env->prepare_buf == NULL) {
                prepare_write_env->prepare_buf = (uint8_t *)malloc(PREPARE_BUF_MAX_SIZE * sizeof(uint8_t));
                prepare_write_env->prepare_len = 0;
                if (prepare_write_env->prepare_buf == NULL) {
                    ESP_LOGE(GATTS_TAG, "Gatt_server prep no mem");
                    status = ESP_GATT_NO_RESOURCES;
                }
            }

            esp_gatt_rsp_t *gatt_rsp = (esp_gatt_rsp_t *)malloc(sizeof(esp_gatt_rsp_t));
            if (gatt_rsp) {
                gatt_rsp->attr_value.len = param->write.len;
                gatt_rsp->attr_value.handle = param->write.handle;
                gatt_rsp->attr_value.offset = param->write.offset;
                gatt_rsp->attr_value.auth_req = ESP_GATT_AUTH_REQ_NONE;
                memcpy(gatt_rsp->attr_value.value, param->write.value, param->write.len);
                esp_err_t response_err = esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, gatt_rsp);

                if (response_err != ESP_OK) {
                    ESP_LOGE(GATTS_TAG, "Send response error\n");
                }
                free(gatt_rsp);
            } else {
                ESP_LOGE(GATTS_TAG, "malloc failed, no resource to send response error\n");
                status = ESP_GATT_NO_RESOURCES;
            }

            if (status != ESP_GATT_OK) {
                return;
            }
            memcpy(prepare_write_env->prepare_buf + param->write.offset,
                   param->write.value,
                   param->write.len);
            prepare_write_env->prepare_len += param->write.len;

        }else {
            esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, status, NULL);
        }
    }
}

void example_exec_write_event_env(prepare_type_env_t *prepare_write_env, esp_ble_gatts_cb_param_t *param){
    if (param->exec_write.exec_write_flag != ESP_GATT_PREP_WRITE_EXEC){
        ESP_LOGI(GATTS_TAG,"ESP_GATT_PREP_WRITE_CANCEL");
    }
    if (prepare_write_env->prepare_buf) {
        free(prepare_write_env->prepare_buf);
        prepare_write_env->prepare_buf = NULL;
    }
    prepare_write_env->prepare_len = 0;
}

static void gatts_profile_a_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param) {
    switch (event) {
    case ESP_GATTS_REG_EVT:
        ESP_LOGI(GATTS_TAG, "REGISTER_APP_EVT, status %d, app_id %d", param->reg.status, param->reg.app_id);
        gl_profile_tab[PROFILE_A_APP_ID].service_id.is_primary = true;
        gl_profile_tab[PROFILE_A_APP_ID].service_id.id.inst_id = 0x00;
        gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.len = ESP_UUID_LEN_16;
        gl_profile_tab[PROFILE_A_APP_ID].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_TEST_A;
        gl_profile_tab[PROFILE_A_APP_ID].gatts_if = gatts_if;
        esp_err_t set_dev_name_ret = esp_ble_gap_set_device_name(TEST_DEVICE_NAME);
        if (set_dev_name_ret){
            ESP_LOGE(GATTS_TAG, "set device name failed, error code = %x", set_dev_name_ret);
        }
#ifdef CONFIG_EXAMPLE_SET_RAW_ADV_DATA
        esp_err_t raw_adv_ret = esp_ble_gap_config_adv_data_raw(raw_adv_data, sizeof(raw_adv_data));
        if (raw_adv_ret){
            ESP_LOGE(GATTS_TAG, "config raw adv data failed, error code = %x ", raw_adv_ret);
        }
        adv_config_done |= adv_config_flag;
        esp_err_t raw_scan_ret = esp_ble_gap_config_scan_rsp_data_raw(raw_scan_rsp_data, sizeof(raw_scan_rsp_data));
        if (raw_scan_ret){
            ESP_LOGE(GATTS_TAG, "config raw scan rsp data failed, error code = %x", raw_scan_ret);
        }
        adv_config_done |= scan_rsp_config_flag;
#else
        //config adv data
        esp_err_t ret = esp_ble_gap_config_adv_data(&adv_data);
        if (ret){
            ESP_LOGE(GATTS_TAG, "config adv data failed, error code = %x", ret);
        }
        adv_config_done |= adv_config_flag;
        //config scan response data
        ret = esp_ble_gap_config_adv_data(&scan_rsp_data);
        if (ret){
            ESP_LOGE(GATTS_TAG, "config scan response data failed, error code = %x", ret);
        }
        adv_config_done |= scan_rsp_config_flag;

#endif
        esp_ble_gatts_create_service(gatts_if, &gl_profile_tab[PROFILE_A_APP_ID].service_id, GATTS_NUM_HANDLE_TEST_A);
        break;
    case ESP_GATTS_READ_EVT: {
        ESP_LOGI(GATTS_TAG, "GATT_READ_EVT, conn_id %d, trans_id %" PRIu32 ", handle %d", param->read.conn_id, param->read.trans_id, param->read.handle);
        esp_gatt_rsp_t rsp;
        memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
        rsp.attr_value.handle = param->read.handle;
        rsp.attr_value.len = 4;
        rsp.attr_value.value[0] = 0xde;
        rsp.attr_value.value[1] = 0xed;
        rsp.attr_value.value[2] = 0xbe;
        rsp.attr_value.value[3] = 0xef;
        esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id,
                                    ESP_GATT_OK, &rsp);
        break;
    }
    case ESP_GATTS_WRITE_EVT: {
#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
        if (!param->write.is_prep){
            if (gl_profile_tab[PROFILE_A_APP_ID].descr_handle == param->write.handle && param->write.len == 2){
                uint16_t descr_value = param->write.value[1]<<8 | param->write.value[0];
                if (descr_value == 0x0001){
                    if (a_property & ESP_GATT_CHAR_PROP_BIT_NOTIFY){

                        ESP_LOGI(GATTS_TAG, "notify enable");
                        can_send_notify = true;
                        xSemaphoreGive(gatts_semaphore);
                    }
                }else if (descr_value == 0x0002){
                    if (a_property & ESP_GATT_CHAR_PROP_BIT_INDICATE){
                        ESP_LOGI(GATTS_TAG, "indicate enable");
                        uint8_t indicate_data[600];
                        for (int i = 0; i < sizeof(indicate_data); ++i)
                        {
                            indicate_data[i] = i%0xff;
                        }

                        for (int j = 0; j < 1000; j++) {
                        //the size of indicate_data[] need less than MTU size
                        esp_ble_gatts_send_indicate(gatts_if, param->write.conn_id, gl_profile_tab[PROFILE_A_APP_ID].char_handle,
                                                sizeof(indicate_data), indicate_data, true);
                        }
                    }
                }
                else if (descr_value == 0x0000){
                    can_send_notify = false;
                    a_property = 0;
                    ESP_LOGI(GATTS_TAG, "notify/indicate disable ");
                }else{
                    ESP_LOGE(GATTS_TAG, "unknown descr value");
                    ESP_LOG_BUFFER_HEX(GATTS_TAG, param->write.value, param->write.len);
                }

            }
        }
#endif /* #if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT) */
        example_write_event_env(gatts_if, &a_prepare_write_env, param);
#if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT)
        if (param->write.handle == gl_profile_tab[PROFILE_A_APP_ID].char_handle) {
            // The last value byte is the checksum data, should used to check the data is received corrected or not.
            if (param->write.value[param->write.len - 1] ==
                check_sum(param->write.value, param->write.len - 1)) {
                write_len += param->write.len;
            }

            if (start == false) {
                start_time = esp_timer_get_time();
                start = true;
                break;
            }
        }
#endif /* #if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT) */

        break;
    }
    case ESP_GATTS_EXEC_WRITE_EVT:
        ESP_LOGI(GATTS_TAG,"ESP_GATTS_EXEC_WRITE_EVT");
#if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT)
        if (param->exec_write.exec_write_flag == ESP_GATT_PREP_WRITE_CANCEL) {
            if (write_len > a_prepare_write_env.prepare_len) {
                write_len -= a_prepare_write_env.prepare_len;
            } else {
                write_len = 0;
            }
        }
#endif /* #if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT) */
        esp_ble_gatts_send_response(gatts_if, param->write.conn_id, param->write.trans_id, ESP_GATT_OK, NULL);
        example_exec_write_event_env(&a_prepare_write_env, param);
        break;
    case ESP_GATTS_MTU_EVT:
        ESP_LOGI(GATTS_TAG, "ESP_GATTS_MTU_EVT, MTU %d", param->mtu.mtu);
        is_connect = true;
        break;
    case ESP_GATTS_UNREG_EVT:
        break;
    case ESP_GATTS_CREATE_EVT:
        ESP_LOGI(GATTS_TAG, "CREATE_SERVICE_EVT, status %d,  service_handle %d", param->create.status, param->create.service_handle);
        gl_profile_tab[PROFILE_A_APP_ID].service_handle = param->create.service_handle;
        gl_profile_tab[PROFILE_A_APP_ID].char_uuid.len = ESP_UUID_LEN_16;
        gl_profile_tab[PROFILE_A_APP_ID].char_uuid.uuid.uuid16 = GATTS_CHAR_UUID_TEST_A;

        esp_ble_gatts_start_service(gl_profile_tab[PROFILE_A_APP_ID].service_handle);
        a_property = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY;
        esp_err_t add_char_ret = esp_ble_gatts_add_char(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].char_uuid,
                                                        ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
                                                        a_property,
                                                        &gatts_demo_char1_val, NULL);
        if (add_char_ret){
            ESP_LOGE(GATTS_TAG, "add char failed, error code =%x",add_char_ret);
        }
        break;
    case ESP_GATTS_ADD_INCL_SRVC_EVT:
        break;
    case ESP_GATTS_ADD_CHAR_EVT: {
        uint16_t length = 0;
        const uint8_t *prf_char;

        ESP_LOGI(GATTS_TAG, "ADD_CHAR_EVT, status %d,  attr_handle %d, service_handle %d",
                param->add_char.status, param->add_char.attr_handle, param->add_char.service_handle);
        gl_profile_tab[PROFILE_A_APP_ID].char_handle = param->add_char.attr_handle;
        gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.len = ESP_UUID_LEN_16;
        gl_profile_tab[PROFILE_A_APP_ID].descr_uuid.uuid.uuid16 = ESP_GATT_UUID_CHAR_CLIENT_CONFIG;
        esp_err_t get_attr_ret = esp_ble_gatts_get_attr_value(param->add_char.attr_handle,  &length, &prf_char);
        if (get_attr_ret == ESP_FAIL){
            ESP_LOGE(GATTS_TAG, "ILLEGAL HANDLE");
        }

        ESP_LOGI(GATTS_TAG, "the gatts demo char length = %x", length);
        for(int i = 0; i < length; i++){
            ESP_LOGI(GATTS_TAG, "prf_char[%x] =%x",i,prf_char[i]);
        }
        esp_err_t add_descr_ret = esp_ble_gatts_add_char_descr(gl_profile_tab[PROFILE_A_APP_ID].service_handle, &gl_profile_tab[PROFILE_A_APP_ID].descr_uuid,
                                                                ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE, NULL, NULL);
        if (add_descr_ret){
            ESP_LOGE(GATTS_TAG, "add char descr failed, error code =%x", add_descr_ret);
        }
        break;
    }
    case ESP_GATTS_ADD_CHAR_DESCR_EVT:

        gl_profile_tab[PROFILE_A_APP_ID].descr_handle = param->add_char_descr.attr_handle;
        ESP_LOGI(GATTS_TAG, "ADD_DESCR_EVT, status %d, attr_handle %d, service_handle %d",
                 param->add_char_descr.status, param->add_char_descr.attr_handle, param->add_char_descr.service_handle);
        break;
    case ESP_GATTS_DELETE_EVT:
        break;
    case ESP_GATTS_START_EVT:
        ESP_LOGI(GATTS_TAG, "SERVICE_START_EVT, status %d, service_handle %d",
                 param->start.status, param->start.service_handle);
        break;
    case ESP_GATTS_STOP_EVT:
        break;
    case ESP_GATTS_CONNECT_EVT: {
        ESP_LOGI(GATTS_TAG, "ESP_GATTS_CONNECT_EVT, conn_id %d, remote %02x:%02x:%02x:%02x:%02x:%02x:",
                 param->connect.conn_id,
                 param->connect.remote_bda[0], param->connect.remote_bda[1], param->connect.remote_bda[2],
                 param->connect.remote_bda[3], param->connect.remote_bda[4], param->connect.remote_bda[5]);
        gl_profile_tab[PROFILE_A_APP_ID].conn_id = param->connect.conn_id;
        break;
    }
    case ESP_GATTS_DISCONNECT_EVT:
        is_connect = false;
        ESP_LOGI(GATTS_TAG, "ESP_GATTS_DISCONNECT_EVT");
        esp_ble_gap_start_advertising(&adv_params);
        break;
    case ESP_GATTS_CONF_EVT:
        break;
    case ESP_GATTS_OPEN_EVT:
    case ESP_GATTS_CANCEL_OPEN_EVT:
    case ESP_GATTS_CLOSE_EVT:
    case ESP_GATTS_LISTEN_EVT:
        break;
    case ESP_GATTS_CONGEST_EVT:
#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
        if (param->congest.congested) {
            can_send_notify = false;
        } else {
            can_send_notify = true;
            xSemaphoreGive(gatts_semaphore);
        }
#endif /* #if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT) */
        break;
    default:
        break;
    }
}

static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
    /* If event is register event, store the gatts_if for each profile */
    if (event == ESP_GATTS_REG_EVT) {
        if (param->reg.status == ESP_GATT_OK) {
            gl_profile_tab[param->reg.app_id].gatts_if = gatts_if;
        } else {
            ESP_LOGI(GATTS_TAG, "Reg app failed, app_id %04x, status %d",
                    param->reg.app_id,
                    param->reg.status);
            return;
        }
    }

    /* If the gatts_if equal to profile A, call profile A cb handler,
     * so here call each profile's callback */
    do {
        int idx;
        for (idx = 0; idx < PROFILE_NUM; idx++) {
            if (gatts_if == ESP_GATT_IF_NONE || /* ESP_GATT_IF_NONE, not specify a certain gatt_if, need to call every profile cb function */
                    gatts_if == gl_profile_tab[idx].gatts_if) {
                if (gl_profile_tab[idx].gatts_cb) {
                    gl_profile_tab[idx].gatts_cb(event, gatts_if, param);
                }
            }
        }
    } while (0);
}

#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
static unsigned int check_data = 0;
void throughput_server_task(void *param)
{
    vTaskDelay(2000 / portTICK_PERIOD_MS);
    uint8_t sum = check_sum(indicate_data, sizeof(indicate_data) - 1);
    // Added the check sum in the last data value.
    indicate_data[GATTS_NOTIFY_LEN - 1] = sum;
    uint16_t index = 0, tmp_index;

    while(1) {
        if (!can_send_notify) {
            int res = xSemaphoreTake(gatts_semaphore, portMAX_DELAY);
            assert(res == pdTRUE);
        } else {
            if (is_connect) {
		        camera_fb_t *pic_cam = esp_camera_fb_get();
		        check_data = 0;
		        for(int i = 0; i < pic_cam->len; i++)
		            check_data += pic_cam->buf[i];
		        ESP_LOGI(GATTS_TAG, "Picture taken! Its size was: %zu bytes chksum:0x%08x", pic_cam->len, check_data);
		        pic_packet.frame_cnt++;
		        pic_packet.all_pack_num = pic_cam->len / pic_packet.length + 1;
                int free_buff_num = esp_ble_get_cur_sendable_packets_num(gl_profile_tab[PROFILE_A_APP_ID].conn_id);
                if(free_buff_num > 0) {
                    for( ; free_buff_num > 0; free_buff_num--) {
			            pic_packet.cur_pack_num++;
			            tmp_index = pic_packet_data(&pic_packet, pic_cam->buf + index, pic_cam->len - index);
			            if(index + pic_packet.length <= pic_cam->len) {
			            	esp_ble_gatts_send_indicate(gl_profile_tab[PROFILE_A_APP_ID].gatts_if, gl_profile_tab[PROFILE_A_APP_ID].conn_id,
			            					gl_profile_tab[PROFILE_A_APP_ID].char_handle,
			            					sizeof(packetdata), packetdata, false);
			            } else {
			            	esp_ble_gatts_send_indicate(gl_profile_tab[PROFILE_A_APP_ID].gatts_if, gl_profile_tab[PROFILE_A_APP_ID].conn_id,
			            					gl_profile_tab[PROFILE_A_APP_ID].char_handle,
			            					pic_packet.length + PACK_HEAD_LEN, packetdata, false);
			            	pic_packet.cur_pack_num = 0;
			            	index = 0;
			            	pic_packet.length = sizeof(packetdata) - PACK_HEAD_LEN;
			            	break;
			            }
			            index += tmp_index;
                    }
                } else { //Add the vTaskDelay to prevent this task from consuming the CPU all the time, causing low-priority tasks to not be executed at all.
                    vTaskDelay( 10 / portTICK_PERIOD_MS );
                }
		        esp_camera_fb_return(pic_cam);
                vTaskDelay( 50 / portTICK_PERIOD_MS );
            } else {
                 vTaskDelay(300 / portTICK_PERIOD_MS);
            }
        }

    }
}
#endif

#if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT)
void throughput_cal_task(void *param)
{
    while (1)
    {
        uint32_t bit_rate = 0;
        vTaskDelay(2000 / portTICK_PERIOD_MS);
        if (is_connect && start_time) {
            current_time = esp_timer_get_time();
            bit_rate = write_len * SECOND_TO_USECOND / (current_time - start_time);
            ESP_LOGI(GATTS_TAG, "GATTC write Bit rate = %" PRIu32 " Byte/s, = %" PRIu32 " bit/s, time %d",
                     bit_rate, bit_rate<<3, (int)((current_time - start_time) / SECOND_TO_USECOND));
        }

    }

}
#endif /* #if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT) */

static uint8_t system_stat = 0;
static void key_input_task(void* arg)
{
    uint32_t io_num;
    for (;;) {
        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
            system_stat++;
        }
    }
}

static void led_ctrl_task(void* arg)
{
    uint32_t tmp = 0;
    bool is_charging = false;
    Battery_stat bat_cap;
    for(;;) {
        tmp++;
        is_charging = !(gpio_get_level(1));
        bat_cap = battery_get_stat(); 
        bat_cap = BAT_MID; 
        printf("bat cap:%d charge:%d\n", bat_cap, is_charging);
        if(system_stat%2 || is_charging){
            if(bat_cap == BAT_FULL) {
                gpio_set_level(LED_RED, 1); 
                gpio_set_level(LED_GREEN, 1); 
                if(is_charging)
                    gpio_set_level(LED_BLUE, 0); 
                else
                    gpio_set_level(LED_BLUE, tmp % 2); 
            } else if(bat_cap == BAT_MID) {
                gpio_set_level(LED_RED, 1); 
                if(is_charging)
                    gpio_set_level(LED_GREEN, 0); 
                else
                    gpio_set_level(LED_GREEN, tmp % 2); 
                gpio_set_level(LED_BLUE, 1); 
            } else {
                if(is_charging)
                    gpio_set_level(LED_RED, 0); 
                else
                    gpio_set_level(LED_RED, tmp % 2); 
                gpio_set_level(LED_GREEN, 1); 
                gpio_set_level(LED_BLUE, 1); 
            }
        } else {
            gpio_set_level(LED_RED, 1); 
            gpio_set_level(LED_GREEN, 1); 
            gpio_set_level(LED_BLUE, 1); 
        }

        if(is_connect)
            vTaskDelay(100 / portTICK_PERIOD_MS);
        else
            vTaskDelay(500 / portTICK_PERIOD_MS);
    }
}

void app_main(void)
{
    esp_err_t ret;

    // Initialize NVS.
    ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK( ret );

    ESP_ERROR_CHECK(esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT));

    esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
    ret = esp_bt_controller_init(&bt_cfg);
    if (ret) {
        ESP_LOGE(GATTS_TAG, "%s initialize controller failed", __func__);
        return;
    }

    ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
    if (ret) {
        ESP_LOGE(GATTS_TAG, "%s enable controller failed", __func__);
        return;
    }

    ret = esp_bluedroid_init();
    if (ret) {
        ESP_LOGE(GATTS_TAG, "%s init bluetooth failed", __func__);
        return;
    }
    ret = esp_bluedroid_enable();
    if (ret) {
        ESP_LOGE(GATTS_TAG, "%s enable bluetooth failed", __func__);
        return;
    }

    ret = esp_ble_gatts_register_callback(gatts_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TAG, "gatts register error, error code = %x", ret);
        return;
    }
    ret = esp_ble_gap_register_callback(gap_event_handler);
    if (ret){
        ESP_LOGE(GATTS_TAG, "gap register error, error code = %x", ret);
        return;
    }
    ret = esp_ble_gatts_app_register(PROFILE_A_APP_ID);
    if (ret){
        ESP_LOGE(GATTS_TAG, "gatts app register error, error code = %x", ret);
        return;
    }

    esp_err_t local_mtu_ret = esp_ble_gatt_set_local_mtu(517);
    if (local_mtu_ret){
        ESP_LOGE(GATTS_TAG, "set local  MTU failed, error code = %x", local_mtu_ret);
    }

    // init camera
    if(ESP_OK != init_camera()) {
        return;
    }

    // init picture packet
    ret = pic_packet_init(&pic_packet, packetdata, sizeof(packetdata));
    if(ESP_OK != ret) {
        ESP_LOGE(GATTS_TAG, "picture packet init failed, error code = %x", ret);
	    return;
    }

    // ini the key input
    ret = key_input_init();
    if(ESP_OK != ret) {
        ESP_LOGE(GATTS_TAG, "key input init failed, error code = %x", ret);
	    return;
    }
    xTaskCreate(key_input_task, "key_input_task", 2048, NULL, 10, NULL);

    // init system led control
    gpio_reset_pin(LED_RED);
    gpio_set_direction(LED_RED, GPIO_MODE_OUTPUT);    
    gpio_reset_pin(LED_GREEN);
    gpio_set_direction(LED_GREEN, GPIO_MODE_OUTPUT);    
    gpio_reset_pin(LED_BLUE);
    gpio_set_direction(LED_BLUE, GPIO_MODE_OUTPUT);    
    gpio_set_level(LED_RED, 1); 
    gpio_set_level(LED_GREEN, 1); 
    gpio_set_level(LED_BLUE, 1); 
    xTaskCreate(led_ctrl_task, "led_ctrl_task", 4096, NULL, 10, NULL);

    // init system charge status
    gpio_reset_pin(1);
    gpio_set_direction(1, GPIO_MODE_INPUT);    
    gpio_set_pull_mode(1, GPIO_PULLUP_ONLY);

#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
    // The task is only created on the CPU core that Bluetooth is working on,
    // preventing the sending task from using the un-updated Bluetooth state on another CPU.
    xTaskCreatePinnedToCore(&throughput_server_task, "throughput_server_task", 4096, NULL, 15, NULL, BLUETOOTH_TASK_PINNED_TO_CORE);
#endif

    // init the battery
    ret = battery_init();
    if(ESP_OK != ret) {
        ESP_LOGE(GATTS_TAG, "battery init failed, error code = %x", ret);
    }

#if (CONFIG_EXAMPLE_GATTC_WRITE_THROUGHPUT)
    xTaskCreatePinnedToCore(&throughput_cal_task, "throughput_cal_task", 4096, NULL, 14, NULL, BLUETOOTH_TASK_PINNED_TO_CORE);
#endif

#if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT)
    gatts_semaphore = xSemaphoreCreateBinary();
    if (!gatts_semaphore) {
        ESP_LOGE(GATTS_TAG, "%s, init fail, the gatts semaphore create fail.", __func__);
        return;
    }
#endif /* #if (CONFIG_EXAMPLE_GATTS_NOTIFY_THROUGHPUT) */
    return;
}
